package com.aplink.generic.pojo;

import java.util.ArrayList;
import java.util.Locale;

import android.location.Location;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.google.maps.clustering.ClusterItem;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;

public class GenericObject extends GenericDictionary<String, GenericAttribute>
        implements ClusterItem, Parcelable {
	public static final Parcelable.Creator<GenericObject> CREATOR = new Parcelable.Creator<GenericObject>() {

		@Override
		public GenericObject createFromParcel(final Parcel source) {
			return new GenericObject(source);
		}

		@Override
		public GenericObject[] newArray(final int size) {
			return new GenericObject[size];
		}
	};
	private static final long serialVersionUID = 4050100780368437551L;
	private ObjPropInfo mLatitudeCol;
	private ObjPropInfo mLongitudeCol;
	private Marker mMarker;

	private String objectMappingName;

	public GenericObject() {

	}

	public GenericObject(
	        final GenericDictionary<String, GenericAttribute> hashMap) {
		for (int i = 0; i < hashMap.size(); i++) {
			final int key = hashMap.keyAt(i);
			this.put(key, hashMap.get(key));
		}
	}

	private GenericObject(Parcel source) {
		objectMappingName = source.readString();
		mLongitudeCol = source.readParcelable(ObjPropInfo.class
		        .getClassLoader());
		mLatitudeCol = source
		        .readParcelable(ObjPropInfo.class.getClassLoader());
		int size = source.readInt();
		for (int i = 0; i < size; i++) {
			int key = source.readInt();
			GenericAttribute attribute = source
			        .readParcelable(GenericAttribute.class.getClassLoader());
			this.put(key, attribute);
		}
	}

	@Override
	public GenericObject clone() {
		final GenericObject genericObject = new GenericObject(this);
		genericObject.objectMappingName = this.objectMappingName;
		return genericObject;
	}

	public boolean contains(GenericObject passedObject,
	        ArrayList<String> searchFields) {
		String passedValue = null;
		String objectValue = null;
		boolean result = true;
		for (String searchField : searchFields) {
			passedValue = passedObject.getValue(searchField);
			objectValue = getValue(searchField);
			if (TextUtils.isEmpty(passedValue)
			        || TextUtils.isEmpty(objectValue)) {
				result = result && false;
			}
			result = result && passedValue.equalsIgnoreCase(objectValue);
		}
		return result;
	}

	public boolean contains(final String key,
	        final ArrayList<String> searchFields) {
		String value = null;
		for (final String searchField : searchFields) {
			value = getValue(searchField);
			if (!TextUtils.isEmpty(value)) {
				if (value.toLowerCase(Locale.getDefault()).contains(
				        key.toLowerCase(Locale.getDefault()))) {
					return true;
				}
			}
		}
		return false;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public GenericAttribute get(final String key) {
		return super.get(key);
	}

	public ObjPropInfo getLatitudeCol() {
		return mLatitudeCol;
	}

	public Location getLocation() {
		final float latitude = Float.parseFloat(getValue(mLatitudeCol));
		final float longitude = Float.parseFloat(getValue(mLongitudeCol));
		Location location = new Location(getTableName());
		location.setLatitude(latitude);
		location.setLongitude(longitude);
		return location;
	}

	public ObjPropInfo getLongitudeCol() {
		return mLongitudeCol;
	}

	public Marker getMarker() {
		return mMarker;
	}

	@Override
	public LatLng getPosition() {
		final float latitude = Float.parseFloat(getValue(mLatitudeCol));
		final float longitude = Float.parseFloat(getValue(mLongitudeCol));
		return new LatLng(latitude, longitude);
	}

	public String getTableName() {
		return this.objectMappingName;
	}

	public String getValue(final ObjPropInfo objPropInfo) {
		if (this.get(objPropInfo.getFullColumnName()) == null) {
			return null;
		}
		return this.get(objPropInfo.getFullColumnName()).getValue();
	}

	public String getValue(final String key) {
		if (this.get(key) == null) {
			return null;
		}
		return this.get(key).getValue();
	}

	public boolean isContainValueOf(final ObjPropInfo objPropInfo) {
		if (containsKey(objPropInfo.getFullColumnName())) {
			if (this.get(objPropInfo.getFullColumnName()) != null) {
				return true;
			}
		}
		return false;
	}

	public boolean isNullValue(final String key) {
		if (this.get(key) == null) {
			return true;
		}
		if (this.get(key).getValue() == null) {
			return true;
		}
		return false;
	}

	public void merge(GenericObject genericObject) {
		for (int i = 0; i < genericObject.size(); i++) {
			final int key = genericObject.keyAt(i);
			final GenericAttribute attribute = genericObject.get(key);
			this.put(key, attribute);
		}
	}

	public void put(final String key, final String content) {
		GenericAttribute attribute = this.get(key);
		if (attribute == null) {
			attribute = new GenericAttribute(key, content);
		}
		attribute.setValue(content);
		this.remove(key);
		this.put(key, attribute);
	}

	public void setLatitudeCol(final ObjPropInfo latitudeCol) {
		mLatitudeCol = latitudeCol;
	}

	public void setLongitudeCol(final ObjPropInfo longitudeCol) {
		mLongitudeCol = longitudeCol;
	}

	@Override
	public void setMarker(final Marker marker) {
		mMarker = marker;
	}

	public void setTableName(final String objectMappingName) {
		this.objectMappingName = objectMappingName;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeString(objectMappingName);
		dest.writeParcelable(mLongitudeCol, PARCELABLE_WRITE_RETURN_VALUE);
		dest.writeParcelable(mLatitudeCol, PARCELABLE_WRITE_RETURN_VALUE);
		dest.writeInt(this.size());
		for (int i = 0; i < this.size(); i++) {
			dest.writeInt(keyAt(i));
			dest.writeParcelable(this.valueAt(i),
			        Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
		}
	}
}
